package com.acegear.horizon.controllers;

import com.acegear.horizon.controllers.vo.ResultVO;
import com.acegear.horizon.domain.models.vo.ClubEventReleaseVO;
import com.acegear.horizon.domain.models.ClubEvent;
import com.acegear.horizon.domain.models.constraint.ClubEventState;
import com.acegear.horizon.domain.models.constraint.ClubEventType;
import com.acegear.horizon.domain.models.jpa.*;
import com.acegear.horizon.domain.models.constraint.FeedType;
import com.acegear.horizon.domain.repository.ClubEventRepository;
import com.acegear.horizon.domain.repository.jpa.ClubBaseRepository;
import com.acegear.horizon.domain.repository.jpa.ClubEventMemberRepository;
import com.acegear.horizon.domain.repository.jpa.ClubEventBaseRepository;
import com.acegear.horizon.domain.repository.jpa.ClubDefalutBankCardInfoRepository;
import com.acegear.horizon.domain.repository.ClubRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import net.sf.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Optional;


/**
 * Created by wangsike on 2017/1/9.
 */
@RestController
@RequestMapping("/events")
public class ClubEventController {

    @Autowired
    private ClubEventRepository eventRepository;
    @Autowired
    private  ClubEventMemberRepository clubEventMemberRepository;
    @Autowired
    private ClubRepository clubRepository;
    @Autowired
    private ClubEventBaseRepository clubEventBaseRepository;
    @Autowired
    private ClubDefalutBankCardInfoRepository clubDefalutBankCardInfoRepository;
    @Autowired
    private ClubBaseRepository clubBaseRepository;

    @RequestMapping(value = "/{eventId}", method = RequestMethod.GET)
    public ResultVO getEvent(@PathVariable Long eventId,
                             @RequestHeader(value = "X-Consumer-Username", required = false, defaultValue = "0") Long viewerId) {
        return eventRepository
                .findByEventId(eventId)
                .map(clubEvent -> clubEvent.getEventDetailVO(viewerId))
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }
    /**
     * 获取联办列表
     */
    @RequestMapping(value = "/findClubInfoList" , method = RequestMethod.GET)
    public ResultVO findClubInfoList(){
        List<ClubBase> clubBase = clubBaseRepository.findAll();
        return new ResultVO(clubBase);
    }
    /**
     * 根据俱乐部名称和id查询俱乐部
     */
    @RequestMapping(value = "/findClubInfoListByClubNameOrClubId" ,method = RequestMethod.GET)
    public ResultVO findClubInfoListByClubNameOrClubId(String clubName,Long clubId){
        List<ClubBase> clubBase = clubBaseRepository.findByClubIdOrClubNameLike(clubId,clubName);
        return new ResultVO();
    }
    /**
     * 设置默认银行卡
     */
    @RequestMapping( value = "/setDefaultBank" , method = RequestMethod.POST)
    public ResultVO setDefaultBank(Long clubId,Long cardId ){
        ClubDefalutBankCardInfo cardInfo = new ClubDefalutBankCardInfo(clubId,cardId);
        return new ResultVO(clubDefalutBankCardInfoRepository.save(cardInfo));
    }
    /**
     * 修改默认银行卡配置
     */
    @RequestMapping(value = "/updateDefaultBank",method = RequestMethod.POST)
    public ResultVO updateDefaultBank(Long clubId,Long cardId){
        Optional<ClubDefalutBankCardInfo> clubInfo = clubDefalutBankCardInfoRepository.findByClubId(clubId);
        if(clubInfo.isPresent()){
            clubInfo.get().setCardId(cardId);
        }
        return new ResultVO(clubDefalutBankCardInfoRepository.save(clubInfo.get()));
    }
    /**
     * 获取俱乐部活动成员列表
     * @param clubId
     * @return
     */
    @RequestMapping( value = "findClubEventMerber",method = RequestMethod.GET)
    public  ResultVO findClubEventMerber(Long clubId){
        List<ClubEventMember> memberList = clubEventMemberRepository.findByEventId(clubId);
        return new ResultVO(memberList);
    }
    /**
     * 置顶活动
     */
    @RequestMapping( value = "/topClubEventById",method = RequestMethod.POST)
    public ResultVO topClubEcentById(Long clubId, Long relateId, FeedType feedType){
        Map<String, Boolean> result = new HashMap<>();
        //clubId 俱乐部id，relateId 帖子id feedType状态
        ClubFeed feed = clubRepository.topFeed(clubId, relateId, feedType);
        if (feed == null) {
            return ResultVO.TOP_FAIL;
        }
        result.put("success", true);
        return new ResultVO<>(result);
    }
    /**
     * 删除活动
     */
    @RequestMapping(value = "/deleteClubEventById",method = RequestMethod.POST)
    public ResultVO deleteClubEventById(Long eventId){
        Optional<ClubEventBase> clunEventBase = clubEventBaseRepository.findByClubEventId(eventId);
        if(clunEventBase.isPresent()){
            clunEventBase.get().setDeleted(true);
        }
        clubEventBaseRepository.save(clunEventBase.get());
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("success",true);
        return new ResultVO(map);
    }
    /**
     * 添加活动详情 Add by TreeJohn
     */
    @RequestMapping(value = "/addEventDetail", method = RequestMethod.POST)
    public ResultVO addEventDetail(String jsonDetail) {
    	JSONObject jb = JSONObject.fromObject(jsonDetail);
    	ClubEventReleaseVO releaseVO = (ClubEventReleaseVO)JSONObject.toBean(jb, ClubEventReleaseVO.class);
        System.out.println("ReleaseVO: " + releaseVO);
        System.out.println("getState: " + releaseVO.getEventBase().getState());
        System.out.println("getType: " + releaseVO.getEventBase().getType());
        
        ClubEvent clubEvent = new ClubEvent();
        clubEvent.saveClubEventReleaseVO(releaseVO);
        
        return new ResultVO<>();
    }

    /**
     * 俱乐部活动详情(还缺活动统计) Add by TreeJohn
     */
    @RequestMapping(value = "/getEventDetail", method = RequestMethod.GET)
    public ResultVO getEventDetail(Long eventId) {
    	ClubEvent event = eventRepository.findByEventId(eventId).get();
    	event.setEventQAS(event.getEventQAS());
    	event.setEventInfo(event.getEventInfo().get());
    	
//    	ClubEventReleaseVO eventReleaseVO = new ClubEventReleaseVO();
        return new ResultVO<>(event);
    }
    
    /**
     * 俱乐部活动列表 Add by TreeJohn
     */
    @RequestMapping(value = "/getEvents", method = RequestMethod.GET)
    public ResultVO getEvents(Long clubId, Integer eventState, Integer page, Integer count) {
    	Pageable pageable = new PageRequest(page, count);
    	ClubEventState state;
    	if (eventState == 0) {
    		state = ClubEventState.SIGNUP;
    	} else {
    		state = ClubEventState.END;
    	}
    	
    	List<ClubEvent> eventList = eventRepository.findByClubId(clubId, state, pageable).collect(Collectors.toList());
    	System.out.println("getPageNumber: " + pageable.getPageNumber());
    	System.out.println("getPageSize: " + pageable.getPageSize());
    	return new ResultVO<>(eventList);
    }

    @RequestMapping(value = "/{eventId}/info", method = RequestMethod.GET)
    public ResultVO getEventInfo(@PathVariable Long eventId) {
        return eventRepository
                .findByEventId(eventId)
                .flatMap(ClubEvent::getEventInfo)
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/qa", method = RequestMethod.POST)
    @Transactional
    public ResultVO createEventQA(@PathVariable Long eventId,
                                  @RequestHeader("X-Consumer-Username") Long userId,
                                  String question) {
        return eventRepository
                .findByEventId(eventId)
                .map(event -> {
                    event.createQA(userId, question);
                    return new HashMap<String, Boolean>() {{
                        put("success", true);
                    }};
                })
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/qa", method = RequestMethod.GET)
    public ResultVO getEventQAs(@PathVariable Long eventId, Integer page, Integer count) {
        Pageable pageable = new PageRequest(page, count);
        return eventRepository
                .findByEventId(eventId)
                .map(event -> event.getQA(pageable))
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/hosts", method = RequestMethod.GET)
    public ResultVO getEventHosts(@PathVariable Long eventId) {
        return eventRepository
                .findByEventId(eventId)
                .map(ClubEvent::getHosts)
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/stages", method = RequestMethod.GET)
    public ResultVO getEventStages(@PathVariable Long eventId) {
        return eventRepository
                .findByEventId(eventId)
                .map(ClubEvent::getEventStages)
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/items/{itemId}", method = RequestMethod.GET)
    public ResultVO getEventItems(@PathVariable Long eventId, @PathVariable Long itemId) {
        return eventRepository
                .findByEventId(eventId)
                .map(event -> event.getEventItem(itemId))
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/orders/{orderId}", method = RequestMethod.PUT)
    @Transactional
    public ResultVO deductOrder(@PathVariable Long eventId, @PathVariable String orderId,
                                @RequestBody EventOrderBody body) {
        return eventRepository
                .findByEventId(eventId)
                .map(event -> {
                    Map<String, Boolean> result = new HashMap<String, Boolean>();
                    result.put("success", event.deductOrder(orderId, body.getUserId(), body.getItems()));
                    return result;
                })
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/orders/{orderId}", method = RequestMethod.DELETE)
    @Transactional
    public ResultVO undoOrder(@PathVariable Long eventId, @PathVariable String orderId) {
        return eventRepository
                .findByEventId(eventId)
                .map(event -> {
                    Map<String, Boolean> result = new HashMap<>();
                    result.put("success", event.undoOrder(orderId));
                    return result;
                })
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "", method = RequestMethod.GET)
    public ResultVO getEvents(Long clubId, ClubEventType eventType, ClubEventState eventState, Integer page, Integer count) {
        PageRequest pageRequest = new PageRequest(page, count);
        return new ResultVO<>(eventRepository
                .queryEvent(clubId, eventType, eventState, pageRequest)
                .map(ClubEvent::getEventVO)
                .collect(Collectors.toList()));
    }

    @RequestMapping(value = "/{eventId}/qa/{qaId}", method = RequestMethod.GET)
    public ResultVO getEventQA(@PathVariable Long eventId, @PathVariable Long qaId) {
        return eventRepository
                .findByEventId(eventId)
                .flatMap(event -> event.getQA(qaId))
                .map(ResultVO::new)
                .orElse(ResultVO.EVENT_NOT_FOUND);
    }

    @RequestMapping(value = "/{eventId}/like", method = RequestMethod.POST)
    @Transactional
    public ResultVO like(@PathVariable Long eventId,
                         @RequestHeader(value = "X-Consumer-Username") Long userId) {
        return eventRepository
                .findByEventId(eventId)
                .filter(event -> event.like(userId))
                .map(event -> {
                    Map<String, Integer> result = new HashMap<>();
                    result.put("likeCount", event.getLikeCount());
                    return new ResultVO<>(result);
                })
                .orElse(ResultVO.EVENT_LIKE_FAILED);
    }

    @RequestMapping(value = "/{eventId}/like", method = RequestMethod.DELETE)
    @Transactional
    public ResultVO unlike(@PathVariable Long eventId,
                           @RequestHeader(value = "X-Consumer-Username") Long userId) {
        return eventRepository
                .findByEventId(eventId)
                .filter(event -> event.unlike(userId))
                .map(event -> {
                    Map<String, Integer> result = new HashMap<>();
                    result.put("likeCount", event.getLikeCount());
                    return new ResultVO<>(result);
                })
                .orElse(ResultVO.EVENT_UNLIKE_FAILED);
    }
}

class EventOrderBody {
    private List<OrderItem> items;

    private Long userId;

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public List<OrderItem> getItems() {
        return items;
    }

    public void setItems(List<OrderItem> items) {
        this.items = items;
    }
}